package user

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"sync"
	"time"

	"golang.org/x/crypto/bcrypt"
)

const (
	// 虚拟IP地址的子网前缀
	virtualIPPrefix = "10.0.0."
	// 会话过期时间
	sessionExpiration = 24 * time.Hour
)

// Service 用户服务接口
type Service interface {
	// 用户管理
	RegisterUser(req RegisterRequest) (*UserResponse, error)
	LoginUser(req LoginRequest) (*SessionResponse, error)
	GetUserStatus(sessionID string) (*StatusResponse, error)
	LogoutUser(sessionID string) error
}

// IPManager 虚拟IP管理器
type IPManager struct {
	mu         sync.Mutex
	usedIPs    map[string]bool
	nextIP     int
	maxClients int
}

// NewIPManager 创建新的IP管理器
func NewIPManager() *IPManager {
	return &IPManager{
		usedIPs:    make(map[string]bool),
		nextIP:     2, // 从10.0.0.2开始分配
		maxClients: 254,
	}
}

// AllocateIP 分配虚拟IP
func (m *IPManager) AllocateIP() (string, error) {
	m.mu.Lock()
	defer m.mu.Unlock()

	if len(m.usedIPs) >= m.maxClients {
		return "", fmt.Errorf("虚拟IP地址已用尽")
	}

	var ip string
	for {
		if m.nextIP > m.maxClients {
			m.nextIP = 2
		}

		ip = fmt.Sprintf("%s%d", virtualIPPrefix, m.nextIP)
		m.nextIP++

		if !m.usedIPs[ip] {
			m.usedIPs[ip] = true
			break
		}
	}

	return ip, nil
}

// ReleaseIP 释放虚拟IP
func (m *IPManager) ReleaseIP(ip string) {
	m.mu.Lock()
	defer m.mu.Unlock()

	delete(m.usedIPs, ip)
}

// DefaultService 默认用户服务实现
type DefaultService struct {
	repo      Repository
	ipManager *IPManager
}

// NewService 创建新的用户服务
func NewService(repo Repository) Service {
	return &DefaultService{
		repo:      repo,
		ipManager: NewIPManager(),
	}
}

// RegisterUser 注册新用户
func (s *DefaultService) RegisterUser(req RegisterRequest) (*UserResponse, error) {
	// 检查用户名是否已存在
	existingUser, err := s.repo.GetUserByUsername(req.Username)
	if err == nil && existingUser != nil {
		return nil, fmt.Errorf("用户名已存在")
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		return nil, fmt.Errorf("密码加密失败: %w", err)
	}

	// 创建用户
	now := time.Now()
	user := &User{
		Username:  req.Username,
		Password:  string(hashedPassword),
		Email:     req.Email,
		CreatedAt: now,
		LastLogin: now,
	}

	userID, err := s.repo.CreateUser(user)
	if err != nil {
		return nil, err
	}

	return &UserResponse{
		ID:       userID,
		Username: user.Username,
	}, nil
}

// LoginUser 用户登录
func (s *DefaultService) LoginUser(req LoginRequest) (*SessionResponse, error) {
	// 查找用户
	user, err := s.repo.GetUserByUsername(req.Username)
	if err != nil {
		return nil, fmt.Errorf("用户不存在")
	}

	// 验证密码
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))
	if err != nil {
		return nil, fmt.Errorf("密码错误")
	}

	// 更新最后登录时间
	now := time.Now()
	err = s.repo.UpdateUserLastLogin(user.ID, now)
	if err != nil {
		return nil, err
	}

	// 分配虚拟IP
	virtualIP, err := s.ipManager.AllocateIP()
	if err != nil {
		return nil, err
	}

	// 生成会话ID
	sessionID, err := generateSessionID()
	if err != nil {
		return nil, fmt.Errorf("生成会话ID失败: %w", err)
	}

	// 创建会话
	expireAt := now.Add(sessionExpiration)
	session := &Session{
		SessionID:  sessionID,
		UserID:     user.ID,
		VirtualIP:  virtualIP,
		CreatedAt:  now,
		ExpireAt:   expireAt,
		LastActive: now,
	}

	err = s.repo.CreateSession(session)
	if err != nil {
		// 如果会话创建失败，释放IP
		s.ipManager.ReleaseIP(virtualIP)
		return nil, err
	}

	return &SessionResponse{
		SessionID: sessionID,
		UserID:    user.ID,
		Username:  user.Username,
		VirtualIP: virtualIP,
		ExpireAt:  expireAt,
	}, nil
}

// GetUserStatus 获取用户状态
func (s *DefaultService) GetUserStatus(sessionID string) (*StatusResponse, error) {
	// 获取会话
	session, err := s.repo.GetSessionByID(sessionID)
	if err != nil {
		return nil, err
	}

	// 检查会话是否过期
	if time.Now().After(session.ExpireAt) {
		s.ipManager.ReleaseIP(session.VirtualIP)
		s.repo.DeleteSession(sessionID)
		return nil, fmt.Errorf("会话已过期")
	}

	// 获取用户信息
	user, err := s.repo.GetUserByID(session.UserID)
	if err != nil {
		return nil, err
	}

	// 更新会话最后活动时间
	now := time.Now()
	s.repo.UpdateSessionLastActive(sessionID, now)

	return &StatusResponse{
		UserID:           user.ID,
		Username:         user.Username,
		VirtualIP:        session.VirtualIP,
		OnlineSince:      session.CreatedAt,
		SessionExpiresAt: session.ExpireAt,
	}, nil
}

// LogoutUser 用户登出
func (s *DefaultService) LogoutUser(sessionID string) error {
	// 获取会话
	session, err := s.repo.GetSessionByID(sessionID)
	if err != nil {
		return nil // 会话不存在或已过期，视为已登出
	}

	// 释放虚拟IP
	s.ipManager.ReleaseIP(session.VirtualIP)

	// 删除会话
	return s.repo.DeleteSession(sessionID)
}

// generateSessionID 生成会话ID
func generateSessionID() (string, error) {
	bytes := make([]byte, 16)
	_, err := rand.Read(bytes)
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(bytes), nil
}
